package qos.estimator.fuzzy;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Random;
import java.util.StringTokenizer;

import fuzzy.NoRulesFiredException;

public class AccuracyTest {
	private ClassificationTuple classificationTuple = new ClassificationTuple();
	private FuzzyEstimator fuzzyEstimator;
	private float sampleSize = 0;
	private int correct, misses, unpredictable  = 0;
	private Collection<String> trainingStatistics = new LinkedList<String>();
	private Collection<String> testingStatistics = new LinkedList<String>();
	

	
	public void startAccuracyTest(){
		try {
			splitFileInTrainingAndTestSets();
			fuzzyEstimator = new FuzzyEstimator(true);
			fuzzyEstimator.inputStatistics(trainingStatistics);
			for (String line : testingStatistics) {
				StringTokenizer result = new StringTokenizer(line, "\t");
				if( result.countTokens() != 0 ) {
					result.nextToken(); //discarding %steal
					classificationTuple.setResidentSetSize(Double.parseDouble(result.nextToken()));
					result.nextToken(); //discarding %guest
					classificationTuple.setMajorFaultsPerSecond(Double.parseDouble(result.nextToken()));
					classificationTuple.setCpuIOWaitPercentual(Double.parseDouble(result.nextToken()));
					classificationTuple.setCpuSoftPercentual(Double.parseDouble(result.nextToken()));
					classificationTuple.setCpuUsrPercentual(Double.parseDouble(result.nextToken()));
					classificationTuple.setMemoryPercentual(Double.parseDouble(result.nextToken()));
					classificationTuple.setDiskUsage(Double.parseDouble(result.nextToken()));
					classificationTuple.setVirtualSize(Double.parseDouble(result.nextToken()));
					classificationTuple.setMinorFaultsPerSecond(Double.parseDouble(result.nextToken()));
					classificationTuple.setInterruptionsPerSecond(Double.parseDouble(result.nextToken()));
					classificationTuple.setCpuSysPercentual(Double.parseDouble(result.nextToken()));
					classificationTuple.setConcSessions(Double.parseDouble( result.nextToken()));
					classificationTuple.setLocks(Double.parseDouble(result.nextToken()));
					classificationTuple.setBuffers(Double.parseDouble(result.nextToken()));
					result.nextToken(); //discarding %nice
					try {
						String expectedElapsedTime = fuzzyEstimator.getExpectedElapsedTimeForQuery(classificationTuple);
						String elapsedTime = fuzzyEstimator.getElapsedTimeLabel(Double.parseDouble(result.nextToken()));
						if(expectedElapsedTime.equals(elapsedTime))
							correct++;
						else{
							misses++;
							/*System.out.println("---------------------");
							System.out.println("Previsto: "+ expectedElapsedTime);
							System.out.println("Real: "+ elapsedTime);*/
						}
						
					} catch (NoRulesFiredException e) {
						unpredictable ++;
						//e.printStackTrace();
					}
					//classificationTuple.setElapsedTime = Double.parseDouble(result.nextToken());
				}
			}
		} catch (FileNotFoundException e) {
			System.err.println("File not found.");
			e.printStackTrace();
		} catch (IOException e) {
			System.err.println("Could not read rules from the specified file.");
			e.printStackTrace();
		} 
		
	}


	private void splitFileInTrainingAndTestSets()
			throws IOException {
		FileReader reader = new FileReader("stats/qosdb.stats");
		BufferedReader bufferedReader = new BufferedReader(reader);
		Random randomNumber = new Random();
		String line = bufferedReader.readLine();
		while(line != null){
			if(randomNumber.nextFloat() <= sampleSize)
				trainingStatistics.add(line);
			else
				testingStatistics.add(line);
			line = bufferedReader.readLine();
		}
		bufferedReader.close();
		reader.close();
	}
	
	public static void main(String[] args) throws IOException {
		FileWriter fw = new FileWriter(new File("stats/fuzzy.result"));
		PrintWriter pw = new PrintWriter(fw);
		float correct, incorrect, unpredictable;
		for (float i = 0.01f; i <= 1f; i+=0.01f) {
			correct = incorrect = unpredictable = 0f;
			for (int j = 0; j < 100; j++) {
				AccuracyTest test = new AccuracyTest();
				test.sampleSize = i;
				test.startAccuracyTest();
				correct += test.correct;
				incorrect += test.misses;
				unpredictable += test.unpredictable;
			}
			
			//System.out.println(i+"\t"+test.trainingStatistics.size()+"\t"+test.testingStatistics.size()+"\t"+(correct/100)+"\t"+(incorrect/100)+"\t"+(unpredictable/100));
			pw.println(i+"\t"+(correct/100)+"\t"+(incorrect/100)+"\t"+(unpredictable/100));
			pw.flush();
		}
		fw.close();
		pw.close();	

		
	}
}
